package com.urbane.gateway.filter;

import com.urbane.gateway.utils.JwtUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

/**
 * 全局 JWT 认证过滤器（执行顺序优先级最高）
 * 功能：
 *   1. 检查请求头中是否携带 Authorization: Bearer <token>
 *   2. 验证 Token 是否有效（签名、过期时间）
 *   3. 从 Token 中提取用户 ID、角色等信息
 *   4. 将用户信息注入 HTTP Header，传递给下游微服务
 *   5. 如果认证失败，直接返回 401 未授权
 * <p>
 * ⚠️ 注意：此过滤器会拦截所有请求，除了 /auth/**（已在路由中跳过）
 */
@Component
public class JwtAuthenticationFilter implements GlobalFilter, Ordered {

    private static final Logger log = LoggerFactory.getLogger(JwtAuthenticationFilter.class);

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        String path = exchange.getRequest().getURI().getPath();

        // 1. 跳过不需要认证的路径（如 /auth/login）
        if (path.startsWith("/auth/")) {
            return chain.filter(exchange); // 直接放行
        }

        // 2. 获取 Authorization 头
        String authorizationHeader = exchange.getRequest().getHeaders().getFirst("Authorization");

        // 3. 验证是否包含 Bearer Token
        if (authorizationHeader == null || !authorizationHeader.startsWith("Bearer ")) {
            log.warn("请求缺少有效的 Authorization 头：{}", path);
            exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
            return exchange.getResponse().setComplete();
        }

        // 4. 提取 Token 字符串
        String token = authorizationHeader.substring(7); // "Bearer " 长度为7

        try {
            // 5. 解析并校验 JWT（验证签名、过期）
            Long userId = JwtUtil.getUserIdFromToken(token);
            String roles = JwtUtil.getRolesFromToken(token); // 如 "USER,ADMIN"

            // 6. 将用户信息注入 Header，传递给下游服务（重要！）
            // 下游服务可通过 Header 获取：X-User-ID, X-Roles
            exchange.getRequest().mutate()
                    .header("X-User-ID", String.valueOf(userId))
                    .header("X-Roles", roles)
                    .build();

            // 7. 将用户ID存入线程上下文（可选，用于日志或内部调用）
            // UserContext.setUser(userId);

            log.info("✅ JWT 验证成功，用户ID: {}, 路径: {}", userId, path);

        } catch (Exception e) {
            log.error("❌ JWT 校验失败，路径: {}, 错误: {}", path, e.getMessage());
            exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
            return exchange.getResponse().setComplete(); // 返回 401
        }

        // 8. 继续执行后续过滤器和目标服务
        return chain.filter(exchange);
    }

    /**
     * 设置过滤器执行顺序，数值越小优先级越高
     * 我们希望它在所有其他过滤器之前执行，所以设为最低值
     */
    @Override
    public int getOrder() {
        return -100; // 比默认过滤器更早执行
    }
}

// Spring Cloud Gateway 全局过滤器 https://docs.springjava.cn/spring-cloud-gateway/reference/spring-cloud-gateway/global-filters.html